#include <Windows.h>
#include <stdio.h>

HANDLE RMutex = NULL, WMutex = NULL;

const int readerCount = 3; //读者个数
const int writerCount = 2; //写者个数
const int threads_num = writerCount + readerCount;
HANDLE Threads[threads_num];

int readcount = 0;

void WINAPI Reader(void *param)
{
    printf("读线程 %u 开始运行\n", GetCurrentThreadId());
    while(true){
        WaitForSingleObject(RMutex, INFINITE);
        if(readcount==0){
            WaitForSingleObject(WMutex, INFINITE);
        }
        readcount++;
        ReleaseMutex(RMutex);

        Sleep(1113);
        printf("读线程 %u 读\n", GetCurrentThreadId());

        WaitForSingleObject(RMutex, INFINITE);
        readcount--;
        if(readcount==0){
            ReleaseMutex(WMutex);
        }
        ReleaseMutex(RMutex);   
        Sleep(1727);     
    }
}

void WINAPI Writer(void *param)
{
    printf("写线程 %u 开始运行\n", GetCurrentThreadId());
    while(true){
        WaitForSingleObject(WMutex, INFINITE);

        Sleep(200);
        printf("写线程 %u 写\n", GetCurrentThreadId());

        ReleaseMutex(WMutex);
        Sleep(1113);
    }
}

void creatThreads()
{
    DWORD dwThreadID = 0;
    for (int i = 0; i < threads_num; i++)
    {
        if (i < writerCount){
            if ((Threads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Writer, NULL, 0, &dwThreadID)) == NULL)
            {
                printf("写线程创建失败！\n");
                exit(0);
            }
            else
            {
                printf("写线程 %u 创建成功\n", dwThreadID);
            }
        }
        else{
            if ((Threads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Reader, NULL, 0, &dwThreadID)) == NULL)
            {
                printf("读线程创建失败！\n");
                exit(0);
            }
            else
            {
                printf("读线程 %u 创建成功\n", dwThreadID);
            }
        }
    }
}

int main()
{
    // 读者优先的读者写者问题-信号量初始化
    printf("赵胜达的读者优先的读者写者问题解决方案：\n");
    RMutex = CreateMutex(NULL, FALSE, "Read");
    WMutex = CreateMutex(NULL, FALSE, "Write");
    // 调用创建进程函数初始化读者和写着进程
    creatThreads();

    WaitForMultipleObjects(threads_num, Threads, TRUE, INFINITE);
    return 0;
}